package com.metadata_system.system.service;

import com.alibaba.fastjson.JSON;
import com.metadata_system.common.db.entity.MetadataEdge;
import com.metadata_system.common.db.entity.UserOperationLog;
import com.metadata_system.common.db.mapper.MetadataEdgeMapper;
import com.metadata_system.common.db.mapper.MetadataViewMapper;
import com.metadata_system.common.db.mapper.UserMapper;
import com.metadata_system.common.dto.ApiResult;
import com.metadata_system.common.enums.AllConst;
import com.metadata_system.common.service.UserOperationLogService;
import com.metadata_system.common.utils.Base62Encoder;
import com.metadata_system.common.utils.MyUtil;
import com.metadata_system.system.request.MetadataEdgeListParams;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class MetadataEdgeService {
    @Autowired(required = false)
    MetadataEdgeMapper metadataEdgeMapper;
    @Autowired(required = false)
    MetadataViewMapper metadataViewMapper;
    @Autowired(required = false)
    UserMapper userMapper;


    @Autowired
    MetadataService metadataService;
    @Autowired
    UserOperationLogService userOperationLogService;


    /**
     * 获取-元数据-关系列表
     *
     * @param listParams
     * @return
     */
    public ApiResult getList(MetadataEdgeListParams listParams) {
        Example example = new Example(MetadataEdge.class);
        Example.Criteria criteria = example.createCriteria();
        if (listParams.getMetadataId() != null) {
            criteria.andEqualTo("metadataId", listParams.getMetadataId());
        }
        if (listParams.getMetadataViewId() != null) {
            criteria.andEqualTo("metadataViewId", listParams.getMetadataViewId());
        }
        if (listParams.getType() != null) {
            criteria.andEqualTo("type", listParams.getType());
        }
        if (listParams.getSourceNodeId() != null) {
            criteria.andEqualTo("sourceNodeId", listParams.getSourceNodeId());
        }
        if (listParams.getTargetNodeId() != null) {
            criteria.andEqualTo("targetNodeId", listParams.getTargetNodeId());
        }
        int total = this.metadataEdgeMapper.selectCountByExample(example);
        List<MetadataEdge> metadataEdges = new ArrayList<>();
        if (total > 0) {
            metadataEdges = this.metadataEdgeMapper.selectByExample(example);
        }
        return ApiResult.successPage(metadataEdges, total);
    }

    /**
     * 新增-元数据-关系
     *
     * @param metadataEdgeParams
     * @param userId             新增用户ID
     * @return
     */
    public ApiResult create(MetadataEdge metadataEdgeParams, Integer userId) {
        if (metadataEdgeParams.getSource() == null) {
            return ApiResult.error("源节点ID 不能为空");
        }
        if (metadataEdgeParams.getTarget() == null) {
            return ApiResult.error("目标节点ID 不能为空");
        }
        if (StringUtils.isBlank(metadataEdgeParams.getName())) {
            return ApiResult.error("元素-名称 不能为空");
        }
        if (metadataEdgeParams.getSourceHandle() == null || !AllConst.MetadataNodeHandleArr.contains(metadataEdgeParams.getSourceHandle())) {
            return ApiResult.error("源节点连线位置 错误");
        }
        if (metadataEdgeParams.getTargetHandle() == null || !AllConst.MetadataNodeHandleArr.contains(metadataEdgeParams.getTargetHandle())) {
            return ApiResult.error("目标节点连线位置 错误");
        }
        if (metadataEdgeParams.getType() == null) {
            return ApiResult.error("线段类型 不能为空");
        }
        if (metadataEdgeParams.getProperties() != null) {
            ApiResult apiResult = MyUtil.checkProperties(metadataEdgeParams.getProperties());
            if (apiResult.isError()) {
                return apiResult;
            }
        } else {
            metadataEdgeParams.setProperties("[]");
        }

        // 同一种类型，使用: 同名+同属性
        Map<String, String> map = this.metadataEdgeMapper.getUniqueKeyByType(metadataEdgeParams.getType(), metadataEdgeParams.getMetadataId());
        if (map != null) {
            metadataEdgeParams.setUniqueKey(map.get("unique_key"));
            metadataEdgeParams.setProperties(map.get("properties"));
        } else {
            metadataEdgeParams.setUniqueKey(Base62Encoder.generateUniqueKey());
        }


        MetadataEdge insertMetadataEdge = MetadataEdge.builder()
                .metadataId(metadataEdgeParams.getMetadataId())
                .metadataViewId(metadataEdgeParams.getMetadataViewId())
                .name(metadataEdgeParams.getName())
                .type(metadataEdgeParams.getType())
                .uniqueKey(metadataEdgeParams.getUniqueKey())
                .source(metadataEdgeParams.getSource())
                .target(metadataEdgeParams.getTarget())
                .sourceHandle(metadataEdgeParams.getSourceHandle())
                .targetHandle(metadataEdgeParams.getTargetHandle())
                .properties(metadataEdgeParams.getProperties())
                .createdTime(new Date())
                .updatedTime(new Date())
                .build();

        this.metadataEdgeMapper.insertSelective(insertMetadataEdge);
        metadataEdgeParams.setId(this.metadataEdgeMapper.getLastInsertId());

        HashMap<String, Object> backMap = new HashMap<>();
        backMap.put("id", "e" + metadataEdgeParams.getId());
        backMap.put("properties", JSON.parseArray(StringUtils.isBlank(metadataEdgeParams.getProperties()) ? "[]" : metadataEdgeParams.getProperties()));
        backMap.put("metadataDetail", metadataService.getDetail(metadataEdgeParams.getMetadataId()).getData());


        userOperationLogService.insert(UserOperationLog.builder()
                .username(userMapper.selectByPrimaryKey(userId).getUsername())
                .userId(userId)
                .type("MetadataEdge.Create")
                .content("新增关系: " + metadataEdgeParams.getName())
                .params(metadataEdgeParams.getId().toString())
                .createdTime(new Date())
                .build());
        return ApiResult.success(backMap);
    }


    public ApiResult update(MetadataEdge metadataEdgeParams, Integer userId) {
        if (metadataEdgeParams.getId() == null) {
            return ApiResult.error("元数据边ID 不能为空");
        }
        MetadataEdge currMetadataEdge = this.metadataEdgeMapper.selectByPrimaryKey(metadataEdgeParams.getId());
        if (currMetadataEdge == null) {
            return ApiResult.error("元数据关系 不存在");
        }

        MetadataEdge updateMetadataEdge = MetadataEdge.builder()
                .id(metadataEdgeParams.getId())
                .build();
        if (metadataEdgeParams.getTarget() != null) {
            if (metadataEdgeParams.getTarget() <= 0) {
                return ApiResult.error("目标节点ID 不能为空");
            }
            updateMetadataEdge.setTarget(metadataEdgeParams.getTarget());
        }
        if (metadataEdgeParams.getTargetHandle() != null) {
            if (!AllConst.MetadataNodeHandleArr.contains(metadataEdgeParams.getSourceHandle())) {
                return ApiResult.error("目标节点连线位置 错误");
            }
            updateMetadataEdge.setTargetHandle(metadataEdgeParams.getTargetHandle());
        }
        if (metadataEdgeParams.getSource() != null) {
            if (metadataEdgeParams.getSource() <= 0) {
                return ApiResult.error("目标节点ID 不能为空");
            }
            updateMetadataEdge.setSource(metadataEdgeParams.getSource());
        }
        if (metadataEdgeParams.getSourceHandle() != null) {
            if (!AllConst.MetadataNodeHandleArr.contains(metadataEdgeParams.getSourceHandle())) {
                return ApiResult.error("源节点连线位置 错误");
            }
            updateMetadataEdge.setSourceHandle(metadataEdgeParams.getSourceHandle());
        }


        // 如果切换类型: 查找是否有已经添加类型: 有则使用，没有则新增
        if (metadataEdgeParams.getType() != null) {
            updateMetadataEdge.setType(metadataEdgeParams.getType());
            Map<String, String> map = this.metadataEdgeMapper.getUniqueKeyByType(metadataEdgeParams.getType(), metadataEdgeParams.getMetadataId());
            if (map != null) {
                metadataEdgeParams.setUniqueKey(map.get("unique_key"));
                metadataEdgeParams.setProperties(map.get("properties"));
            } else {
                metadataEdgeParams.setUniqueKey(Base62Encoder.generateUniqueKey());
            }
        }

        // 更新数据，则所有 uniqueKey 数据都要更新
        if (metadataEdgeParams.getProperties() != null) {
            ApiResult apiResult = MyUtil.checkProperties(metadataEdgeParams.getProperties());
            if (apiResult.isError()) {
                return apiResult;
            }
            updateMetadataEdge.setProperties(metadataEdgeParams.getProperties());
            Example example = new Example(MetadataEdge.class);
            Example.Criteria criteria = example.createCriteria();
            criteria.andEqualTo("metadataId", currMetadataEdge.getMetadataId());
            criteria.andEqualTo("uniqueKey", metadataEdgeParams.getUniqueKey());
            this.metadataEdgeMapper.updateByExampleSelective(MetadataEdge.builder().properties(metadataEdgeParams.getProperties()).build(), example);
        } else {
            this.metadataEdgeMapper.updateByPrimaryKeySelective(metadataEdgeParams);
        }

        userOperationLogService.insert(UserOperationLog.builder()
                .username(userMapper.selectByPrimaryKey(userId).getUsername())
                .userId(userId)
                .type("MetadataEdge.Update")
                .content("更新关系: " + metadataEdgeParams.getName())
                .params(metadataEdgeParams.getId().toString())
                .createdTime(new Date())
                .build());

        // 返回-元数据详情
        return metadataService.getDetail(currMetadataEdge.getMetadataId());
    }

    public ApiResult delete(Integer id, Integer metadataViewId, Integer userId) {
        MetadataEdge metadataEdge = this.metadataEdgeMapper.selectOne(MetadataEdge.builder().id(id).metadataViewId(metadataViewId).build());
        if (metadataEdge == null) {
            return ApiResult.error("元数据关系 不存在");
        }
        this.metadataEdgeMapper.deleteByPrimaryKey(id);

        userOperationLogService.insert(UserOperationLog.builder()
                .username(userMapper.selectByPrimaryKey(userId).getUsername())
                .userId(userId)
                .type("MetadataEdge.Delete")
                .content("删除关系: " + metadataEdge.getName())
                .params(id.toString())
                .createdTime(new Date())
                .build());

        // 返回-元数据详情
        return metadataService.getDetailByVewId(metadataEdge.getMetadataViewId());
    }

    public ApiResult deleteAll(List<Integer> idList, Integer metadataViewId, Integer userId) {
        if (idList == null || idList.isEmpty()) {
            return ApiResult.error("删除关系-参数错误 3");
        }
        Example example = new Example(MetadataEdge.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("metadataViewId", metadataViewId);
        criteria.andIn("id", idList);
        if (this.metadataEdgeMapper.selectCountByExample(example) != idList.size()) {
            return ApiResult.error("删除关系-参数错误 4");
        }
        this.metadataEdgeMapper.deleteByExample(example);

        userOperationLogService.insert(UserOperationLog.builder()
                .username(userMapper.selectByPrimaryKey(userId).getUsername())
                .userId(userId)
                .type("MetadataEdge.DeleteAll")
                .content("批量删除关系: " + idList.size())
                .params(String.join(",", idList.stream().map(String::valueOf).collect(Collectors.toList())))
                .createdTime(new Date())
                .build());

        // 返回-元数据详情
        return metadataService.getDetailByVewId(metadataViewId);
    }
}
